iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 18
1
Mobile Development

Android 開發經驗三十天系列 第 18

[Android 開發經驗三十天]#D18一自定義View小畫家 (畫面設計)

  • 分享至 

  • xImage
  •  

Android 自定義View小畫家 (Activity畫面設計)


tags: 鐵人賽 Templates

那還是稍微講一下畫面設計的部分OuO

畫面設計

紅色框框的LinearLayout

  <LinearLayout
            android:id="@+id/linearLayout3"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent">

            <Button
                android:id="@+id/eraser"
                android:layout_width="40dp"
                android:layout_height="wrap_content"
                android:text="er"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toTopOf="parent" />

            <Button
                android:id="@+id/go"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="paint"
                app:layout_constraintStart_toEndOf="@+id/eraser"
                app:layout_constraintTop_toTopOf="parent" />

            <Button
                android:id="@+id/back"
                android:layout_width="40dp"
                android:layout_height="wrap_content"
                android:text="b"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintHorizontal_bias="0.0"
                app:layout_constraintStart_toEndOf="@+id/go"
                app:layout_constraintTop_toTopOf="parent" />
            <Button
                android:id="@+id/next"
                android:text="n"
                android:layout_width="40dp"
                android:layout_height="wrap_content"/>
            <Button
                android:id="@+id/save"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="save"/>
            <Button
                android:id="@+id/turn"
                android:layout_width="40dp"
                android:layout_height="wrap_content"
                android:text="t"/>
        </LinearLayout>


重點就是在按eraser跟paint的時候才會顯示那塊橘色的
按下eraser顯示的seekbar

  <SeekBar
            android:id="@+id/widthprogress"
            android:layout_width="0dp"
            android:layout_height="25dp"
            android:visibility="gone"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="@+id/linearLayout3"
            app:layout_constraintTop_toBottomOf="@+id/linearLayout3" />

按下paint顯示橘色的一整塊
黃色的seekbar

 <SeekBar
            android:visibility="gone"
            android:id="@+id/transparenctbar"
            android:layout_width="0dp"
            android:layout_height="25dp"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/widthprogress" />

藍色的seekbar

  <SeekBar
            android:visibility="gone"
            android:id="@+id/transparenctbar"
            android:layout_width="0dp"
            android:layout_height="25dp"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/widthprogress" />
            

綠色的那塊放現在有甚麼顏色的選擇框

    <LinearLayout
        android:id="@+id/chColorLayout"
        android:visibility="gone"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/transparenctbar">

        <Button
            android:id="@+id/red"
            android:layout_width="40dp"
            android:layout_height="40dp"
            android:layout_margin="10dp"
            android:background="@color/colorRed" />

        <Button
            android:id="@+id/yellow"
            android:layout_width="40dp"
            android:layout_height="40dp"
            android:layout_margin="10dp"
            android:background="@color/colorYy" />
    </LinearLayout>
    

Activity邏輯

1.宣告所有button與相關變數

var turn : Button=findViewById(R.id.turn)
        var eraser : Button=findViewById(R.id.eraser)
        var back : Button=findViewById(R.id.back)
        var go : Button=findViewById(R.id.go)
        var save : Button=findViewById(R.id.save)
        var next : Button=findViewById(R.id.next)
        var prgress_width:SeekBar=findViewById(R.id.widthprogress)
        var eraser_width:SeekBar=findViewById(R.id.eraserprogress)
        var transparentbar:SeekBar=findViewById(R.id.transparenctbar)
        var colorRed:Button=findViewById(R.id.red)
        var colorYellow:Button=findViewById(R.id.yellow)
        var chColorLayout:View=findViewById(R.id.chColorLayout)
          var cl=Color.BLACK
        var clickit=false
        var clickNext=false
        eraser.isEnabled=false

2.繪圖按下功能

邏輯:其他不相關的layout隱藏,只顯示自己要的
按一下顯示,按一下隱藏
按下畫筆時橡皮擦不能同時按
按畫筆時設定寬高跟顏色

  go.setOnClickListener {
            eraser_width.visibility=View.GONE
            clickit=!clickit
            if (clickit){
                eraser.isEnabled=false
                transparentbar.visibility=View.VISIBLE
                prgress_width.visibility=View.VISIBLE
                chColorLayout.visibility=View.VISIBLE
            }
            else{
                eraser.isEnabled=true
                transparentbar.visibility=View.GONE
                prgress_width.visibility=View.GONE
                chColorLayout.visibility=View.GONE
            }
            var trans=255
            paintView.setWidth(10)
            prgress_width.setOnSeekBarChangeListener(object :SeekBar.OnSeekBarChangeListener{
                override fun onProgressChanged(p0: SeekBar?, p1: Int, p2: Boolean) {
                    var a=p0!!.progress
                    paintView.setWidth(a)
                }

                override fun onStartTrackingTouch(p0: SeekBar?) {

                }
                override fun onStopTrackingTouch(p0: SeekBar?) {

                }
            })
            
             transparentbar.setOnSeekBarChangeListener(object:SeekBar.OnSeekBarChangeListener{
                override fun onProgressChanged(p0: SeekBar?, p1: Int, p2: Boolean) {
                    var percent=p0!!.progress
                    trans=(256/100)*percent
                    paintView.setColor(cl,trans)
                }

                override fun onStartTrackingTouch(p0: SeekBar?) {

                }

                override fun onStopTrackingTouch(p0: SeekBar?) {

                }


            } )
            colorRed.setOnClickListener {
                cl=Color.RED
                paintView.setColor(cl,trans)
                Log.d("color","red"+cl+trans)
            }
            colorYellow.setOnClickListener {
                cl=Color.YELLOW
                paintView.setColor(cl,trans)
            }
            Log.d("color","activity"+cl+"tt"+trans)
        }

3.儲存照片功能


        save.setOnClickListener {
            viewSaveToImage(paintView)
        }
  fun viewSaveToImage(view: PPView) {
...}

重點
1.要先拿到bitmap

PPView內增加
w跟h是拿現在有多寬,在用createBitmap創造出來,在創canvas跟draw return回去
如果沒有canvas跟draw就會是黑色的圖不會有內容。

  public Bitmap loadBitmapFromView() {
        int w = getWidth();
        int h = getHeight();
        Bitmap bmp = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
        Canvas c =new Canvas(bmp);
        draw(c);
        return bmp;
    }

2.拿到bitmap後決定要儲存的路徑,用new File創一個新路徑,在判斷他存在與否不存在才創建

 val cachebmp = view.loadBitmapFromView()
  var appDir =  File(Environment.getExternalStorageDirectory(), "Boohee");
            if (!appDir.exists()) {
                appDir.mkdir();
            }

3.寫入,用outputStream寫入,在compress(壓縮他)最後記得flush跟close

val file = File(appDir, "test.PNG")
fos = FileOutputStream(file)
            cachebmp.compress(Bitmap.CompressFormat.PNG, 100, fos)
            fos.flush()
            fos.close()

4.前進/後退按鈕

    
        back.setOnClickListener {
            paintView.back()
        }

        next.setOnClickListener {
            paintView.next()
        }

5.橡皮擦功能

一樣監聽progressBar,和橡皮擦打開時畫筆不能同時打開

   eraser.setOnClickListener {

            clickNext=!clickNext
            var progress=0
            if (clickNext){
                go.isEnabled=false
                prgress_width.visibility=View.GONE
                chColorLayout.visibility=View.GONE
                transparentbar.visibility=View.GONE
                eraser_width.visibility=View.VISIBLE
                eraser_width.setOnSeekBarChangeListener(object :SeekBar.OnSeekBarChangeListener{
                    override fun onProgressChanged(p0: SeekBar?, p1: Int, p2: Boolean) {
                        progress=p0!!.progress
                        paintView.setWidth(progress)
                    }

                    override fun onStartTrackingTouch(p0: SeekBar?) {

                    }

                    override fun onStopTrackingTouch(p0: SeekBar?) {

                    }
                })
            }else{
                go.isEnabled=true
                prgress_width.visibility=View.GONE
                eraser_width.visibility=View.GONE
            }
            paintView.eraserIt()

        }
      

全部

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <LinearLayout
            android:id="@+id/linearLayout3"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent">

            <Button
                android:id="@+id/eraser"
                android:layout_width="40dp"
                android:layout_height="wrap_content"
                android:text="er"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toTopOf="parent" />

            <Button
                android:id="@+id/go"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="paint"
                app:layout_constraintStart_toEndOf="@+id/eraser"
                app:layout_constraintTop_toTopOf="parent" />

            <Button
                android:id="@+id/back"
                android:layout_width="40dp"
                android:layout_height="wrap_content"
                android:text="b"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintHorizontal_bias="0.0"
                app:layout_constraintStart_toEndOf="@+id/go"
                app:layout_constraintTop_toTopOf="parent" />
            <Button
                android:id="@+id/next"
                android:text="n"
                android:layout_width="40dp"
                android:layout_height="wrap_content"/>
            <Button
                android:id="@+id/save"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="save"/>
            <Button
                android:id="@+id/turn"
                android:layout_width="40dp"
                android:layout_height="wrap_content"
                android:text="t"/>
        </LinearLayout>


        <SeekBar
            android:id="@+id/widthprogress"
            android:layout_width="0dp"
            android:layout_height="25dp"
            android:visibility="gone"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="@+id/linearLayout3"
            app:layout_constraintTop_toBottomOf="@+id/linearLayout3" />

        <SeekBar
            android:visibility="gone"
            android:id="@+id/transparenctbar"
            android:layout_width="0dp"
            android:layout_height="25dp"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/widthprogress" />
        <SeekBar
            android:visibility="gone"
            android:id="@+id/eraserprogress"
            android:layout_width="0dp"
            android:layout_height="25dp"

            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="@+id/linearLayout3"
            app:layout_constraintTop_toBottomOf="@+id/linearLayout3" />
<!--  android:visibility="gone"-->

        <LinearLayout
            android:id="@+id/chColorLayout"
            android:visibility="gone"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/transparenctbar">

            <Button
                android:id="@+id/red"
                android:layout_width="40dp"
                android:layout_height="40dp"
                android:layout_margin="10dp"
                android:background="@color/colorRed" />

            <Button
                android:id="@+id/yellow"
                android:layout_width="40dp"
                android:layout_height="40dp"
                android:layout_margin="10dp"
                android:background="@color/colorYy" />
        </LinearLayout>

    </androidx.constraintlayout.widget.ConstraintLayout>

<com.example.ktforfilemanager.paintview.PPView

    android:background="@color/colorWhite"
    android:id="@+id/paintView"
    android:layout_width="match_parent"
    android:layout_height="match_parent"/>

上一篇
[Android 開發經驗三十天]#D17一自定義View小畫家 (下)
下一篇
[Android 開發經驗三十天]#D19一LiveData && MVVM && MVP介紹
系列文
Android 開發經驗三十天30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言